// #pragma once

// #include <pthread.h>

// class Lock
// {
// public:
//     Lock()
//     {
//         pthread_mutex_init(&_pmutex, nullptr);
//     }

//     ~Lock()
//     {
//         pthread_mutex_destroy(&_pmutex);
//     }

//     void lock()
//     {
//         pthread_mutex_lock(&_pmutex);
//     }

//     void unlock()
//     {
//         pthread_mutex_unlock(&_pmutex);
//     }
// private:
//     pthread_mutex_t _pmutex;
// };

// class LockGuard
// {
// public:
//     LockGuard(Lock pmutex):_pmutex(pmutex)
//     {
//         _pmutex.lock();
//     }

//     ~LockGuard()
//     {
//         _pmutex.unlock();
//     }
// private:
//     Lock _pmutex;
// };

#pragma once

#include <iostream>
#include <pthread.h>
using namespace std;

class Cond
{
public:
    Cond()
    {
        pthread_cond_init(&_cond, nullptr);
    }

    void wait(pthread_mutex_t *pmutex)
    {
        pthread_cond_wait(&_cond, pmutex);
    }

    void signal()
    {
        pthread_cond_signal(&_cond);
    }

    void broadcast()
    {
        pthread_cond_broadcast(&_cond);
    }

    ~Cond()
    {
        pthread_cond_destroy(&_cond);
    }

private:
    pthread_cond_t _cond;
};

class Lock
{
public:
    Lock()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }

    ~Lock()
    {
        pthread_mutex_destroy(&_mutex);
    }

    void lock()
    {
        pthread_mutex_lock(&_mutex);
    }

    void unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }

    pthread_mutex_t *ret_mutex()
    {
        return &_mutex;
    }

private:
    pthread_mutex_t _mutex;
};

class LockGuard
{
public:
    LockGuard(Lock *pmutex) : _pmutex(pmutex)
    {
        _pmutex->lock();
    }

    ~LockGuard()
    {
        _pmutex->unlock();
    }

private:
    Lock *_pmutex;
};